#include "Application.h"
#include <QDebug>
#include <QDir>
#include <QDateTime>
#include <QSharedMemory>

#include <QTranslator>

#ifdef Q_OS_WIN
#define NOMINMAX

#include <crash_report_database.h>
#include <settings.h>
#include <crashpad_client.h>
#else
#include <client/crash_report_database.h>
#include <client/settings.h>
#include <client/crashpad_client.h>
#endif

#include "common/QtAppMacro.h"
#include "helper/DirHelper.h"
#include "helper/ConfigHelper.h"
#include "log/TSpdlog.h"

bool Application::setSingleApp(const char* uniqueProgram)
{
#ifdef Q_OS_WIN
    static QSharedMemory shm(uniqueProgram);
    if(shm.create(2) == false){
        return true;
    }
    return false;
#else
    return false;
#endif
}

bool Application::init()
{
    if (QString("") == REG_QT_APP_DATA || QString("") == APP_COMPANY_NAME || QString("") == APP_COMPANY_APP_NAME) {
        qDebug() << "error :please set default value";
        return false;
    }

    QApplication::setOrganizationName(APP_COMPANY_NAME);
    QApplication::setOrganizationDomain(APP_COMPANY_URL);
    QApplication::setApplicationName(APP_COMPANY_APP_NAME);

    return true;
}

bool Application::startCrashHandler()
{
    using namespace crashpad;

    std::map<std::string, std::string> annotations;
    std::vector<std::string> arguments;
    CrashpadClient client;
    bool rc;

    /*
     * ENSURE THIS VALUE IS CORRECT.
     *
     * This is the directory you will use to store and
     * queue crash data.
     */

    /*
     * ENSURE THIS VALUE IS CORRECT.
     *
     * Crashpad has the ability to support crashes both in-process
     * and out-of-process. The out-of-process handler is
     * significantly more robust than traditional in-process crash
     * handlers. This path may be relative.
     */
#ifdef Q_OS_WIN
    std::wstring db_path(DirHelper::getInstance()->dumpPath().toStdWString().c_str());
    std::wstring handler_path(L"crashpad_handler.exe");
#else
    std::string db_path("/Users/sl/dump");
    std::string handler_path("/Users/sl/dump/crashpad_handler");
#endif

    /*
     * YOU MUST CHANGE THIS VALUE.
     *
     * Update the <Universe> and <Token> in the below
     */
    std::string url("your");

    annotations["format"] = "";
    annotations["token"] = "855a5c717a51bb13f45b5a899b592cb4eff29e345f676a79ae2cd4487f555406";
    /*
     * REMOVE THIS FOR ACTUAL BUILD.
     *
     * To disable crashpad’s default limitation of
     * 1 upload per hour, pass the --no-rate-limit
     * argument to the handler
     *
     */
    arguments.push_back("--no-rate-limit");

    base::FilePath db(db_path);
    base::FilePath handler(handler_path);

    std::unique_ptr<CrashReportDatabase> database =
            crashpad::CrashReportDatabase::Initialize(db);

    if (database == nullptr || database->GetSettings() == NULL)
        return false;

    /* Enable automated uploads. */
    database->GetSettings()->SetUploadsEnabled(true);

    rc = client.StartHandler(handler,
                             db,
                             db,
                             url,
                             annotations,
                             arguments,
                             true,
                             true);
    if (rc == false)
        return false;

    /* Optional, wait for Crashpad to initialize. */
#ifdef Q_OS_WIN
    rc = client.WaitForHandlerStart(INFINITE);
    if (rc == false)
        return false;
#endif

    return true;
}

Application::Application(int &argc, char **argv):QApplication(argc,argv)
{
    initDir();
    initConfig();
    initLog();
    qDebug() << "crash init:" << startCrashHandler();
}

Application::~Application()
{
}

void Application::initDir()
{
    DirHelper::getInstance();
}

void Application::initLog()
{
    QString path = DirHelper::getInstance()->logPath();
    path = path + QDir::separator() + "MyAPP_" + QDateTime::currentDateTime().toString("yyyyMMdd") + ".log";
    TSpdlog::registerLog(path.toStdString().c_str(),path.toStdString().c_str());
    TSpdlog::getInstance();
}

void Application::initConfig()
{
    ConfigHelper::getInstance();
}

bool Application::addTranslation()
{
    /* 翻译文件 */
    QTranslator *trans = new QTranslator;
    QString path;
    if (ConfigHelper::getInstance()->getLanguage() == "CN") {
        path = DirHelper::getInstance()->getAppPath() + "/lang_Chinese.qm";
    } else {
        path = DirHelper::getInstance()->getAppPath() + "/lang_English.qm";
    }
    if (trans->load(path) ) {
        installTranslator(trans);
        return true;
    } else {
        TSpdlog::getInstance()->otherError("translator error" + path);
        return false;
    }
}
